/// <summary>
// DBLinq.MySqlProviders - .NET Providers for MySql using the framework DBLinq under MIT license, author Jiri George Moudry
// http://linq.to/db
// and the CodeFx.MySqlProviders under GNU licence, author Laurent Morisseau
// http://www.codeplex.com/CodeFxMySqlProvider
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Laurent Morisseau
/// </summary>
/// <author><a href="mailto:laurent.morisseau@gmail.com">Laurent Morisseau</a></author>

using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
namespace DBLinq.MySqlProviders
{

    public sealed class MySqlRoleProvider : RoleProvider
    {

    
        private string _AppName;
    
        public override void Initialize(string name, NameValueCollection config)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            if (string.IsNullOrEmpty(name))
            {
                name = "MySqlRoleProvider";
            }
            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "RoleSqlProvider_description");
            }
            base.Initialize(name, config);
            string text1 = config["connectionStringName"];
            if (string.IsNullOrEmpty(text1))
            {
                throw new ProviderException("Connection_name_not_specified");
            }
            /// ConnectionString
            ConnectionString.Current.CurrentString = ConfigurationManager.ConnectionStrings[config["connectionStringName"]].ConnectionString;
           
            this._AppName = config["applicationName"];
            if (string.IsNullOrEmpty(this._AppName))
            {
                this._AppName = "Code1";
            }
            if (this._AppName.Length > 0x100)
            {
                throw new ProviderException("Provider_application_name_too_long");
            }
            config.Remove("connectionStringName");
            config.Remove("applicationName");
            config.Remove("commandTimeout");
            if (config.Count > 0)
            {
                string text2 = config.GetKey(0);
                if (!string.IsNullOrEmpty(text2))
                {
                    throw new ProviderException("Provider_unrecognized_attribute");
                }
            }

        }

        public override string ApplicationName
        {
            get { return _AppName; }
            set { _AppName = value; }
        }

        public override void AddUsersToRoles(string[] usernames, string[] rolenames)
        {
            SecUtility.CheckArrayParameter(ref rolenames, true, true, true, 0x100, "rolenames");
            SecUtility.CheckArrayParameter(ref usernames, true, true, true, 0x100, "usernames");

            foreach (string rolename in rolenames)
            {
                if (!RoleExists(rolename))
                {
                    throw new ProviderException("Role name not found.");
                }
            }

            foreach (string username in usernames)
            {
                if (username.IndexOf(',') > 0)
                {
                    throw new ArgumentException("User names cannot contain commas.");
                }

                foreach (string rolename in rolenames)
                {
                    if (IsUserInRole(username, rolename))
                    {
                        throw new ProviderException("User is already in role.");
                    }
                }
            }
            
            AspNetUsersInRole usersinroles = new AspNetUsersInRole();
            uint appid = ApplicationId;
            foreach (string username in usernames)
            {
                foreach (string rolename in rolenames)
                {
                    usersinroles.UserId = AspNetUsersDTO.GetUserId(username, appid);
			  usersinroles.RoleId = AspNetRolesDTO.GetRoleId(rolename, appid);

                    if (usersinroles.UserId == 0)
                    {
                        AspNetUser user = new AspNetUser();
                        user.ApplicationId = appid;
                        user.IsAnonymous = false;
                        user.LastActivityDate = DateTime.UtcNow;
                        user.UserName = username;
                        AspNetUsersDTO.Insert(user);

                        usersinroles.UserId = AspNetUsersDTO.GetLastId(user);
                    }
                    AspNetUsersInRolesDTO.Insert(usersinroles);
                }
            }
        }

        public override void CreateRole(string rolename)
        {
            SecUtility.CheckParameter(ref rolename, true, true, true, 0x100, "roleName");
            if (!AspNetApplicationsDTO.Exist(this.ApplicationName))
            {
                AspNetApplication app = new AspNetApplication();
                app.ApplicationName = this.ApplicationName;
                AspNetApplicationsDTO.Insert(app);
            }

            if (!AspNetRolesDTO.Exist(rolename))
            {
                AspNetRole role = new AspNetRole ();
                role.ApplicationId = ApplicationId;
                role.RoleName = rolename;
                AspNetRolesDTO.Insert(role);
            }

        }

        public override bool DeleteRole(string rolename, bool throwOnPopulatedRole)
        {
            SecUtility.CheckParameter(ref rolename, true, true, true, 0x100, "roleName");
            uint appid = ApplicationId;
            uint roleid = AspNetRolesDTO.GetRoleId(rolename, appid);
            if (roleid == 0)
                return false;
            if (throwOnPopulatedRole && AspNetUsersInRolesDTO.Exist(roleid))
                throw new ProviderException("Role_is_not_empty");
		AspNetUsersInRolesDTO.DeleteByFk_RoleId ( roleid );
		AspNetRolesDTO.DeleteByFk_ApplicationId_RoleId ( appid, roleid );
            return true;
        }

        public override string[] GetAllRoles()
        {
		  IEnumerable<AspNetRole> roles = AspNetRolesDTO.SelectByFk_ApplicationId ( ApplicationId );
            StringCollection collection1 = new StringCollection();
            foreach (AspNetRole role in roles)
            {
                collection1.Add(role.RoleName);
            }
            string[] textArray1 = new string[collection1.Count];
            collection1.CopyTo(textArray1, 0);
            return textArray1;
        }

        public override string[] GetRolesForUser(string username)
        {
            SecUtility.CheckParameter(ref username, true, false, true, 0x100, "username");
            if (username.Length < 1)
            {
                return new string[0];
            }
            uint appid = ApplicationId;
            uint userid = AspNetUsersDTO.GetUserId(username, appid);
            if (userid == 0)
                return new string[0];
            StringCollection collection1 = AspNetRolesDTO.UsersInRoles_GetRolesForUser(appid, userid);
            if ((collection1 != null) && (collection1.Count > 0))
            {
                string[] textArray1 = new string[collection1.Count];
                collection1.CopyTo(textArray1, 0);
                return textArray1;
            }
            return new string[0];
        }

        public override string[] GetUsersInRole(string rolename)
        {
            SecUtility.CheckParameter(ref rolename, true, true, true, 0x100, "roleName");
            uint appid = ApplicationId;
            uint roleid = AspNetRolesDTO.GetRoleId(rolename, appid);
            if (roleid == 0)
                return new string[0];
            StringCollection collection1 = AspNetUsersDTO.UsersInRoles_GetUsersInRoles (appid, roleid);
            if ((collection1 != null) && (collection1.Count > 0))
            {
                string[] textArray1 = new string[collection1.Count];
                collection1.CopyTo(textArray1, 0);
                return textArray1;
            }
            return new string[0];
        }

        public override bool IsUserInRole(string username, string rolename)
        {
            SecUtility.CheckParameter(ref rolename, true, true, true, 0x100, "roleName");
            SecUtility.CheckParameter(ref username, true, false, true, 0x100, "username");
            if (username.Length < 1)
            {
                return false;
            }

            uint appid = ApplicationId;
            if (appid == 0)
                return false;
            
            uint userid = AspNetUsersDTO.GetUserId(username, appid);
            if (userid == 0)
                return false;
            
            uint roleid = AspNetRolesDTO.GetRoleId(rolename, appid);
            if (roleid == 0)
                return false;

            return AspNetUsersInRolesDTO.Exist(userid,roleid);
            
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] rolenames)
        {
            foreach (string rolename in rolenames)
            {
                if (!RoleExists(rolename))
                {
                    throw new ProviderException("Role name not found.");
                }
            }

            foreach (string username in usernames)
            {
                foreach (string rolename in rolenames)
                {
                    if (!IsUserInRole(username, rolename))
                    {
                        throw new ProviderException("User is not in role.");
                    }
                }
            }
            uint appid = ApplicationId;

            foreach (string username in usernames)
            {
                foreach (string rolename in rolenames)
                {
                    uint UserId = AspNetUsersDTO.GetUserId(username, appid);
                    uint RoleId = AspNetRolesDTO.GetRoleId(rolename, appid);

			  AspNetUsersInRolesDTO.DeleteByFk_UserId_RoleId ( UserId, RoleId );
                }
            }

        }

        public override bool RoleExists(string rolename)
        {
            SecUtility.CheckParameter(ref rolename, true, true, true, 0x100, "roleName");
            return (AspNetRolesDTO.GetRoleId(rolename, ApplicationId)>0);
        }

        public override string[] FindUsersInRole(string rolename, string usernameToMatch)
        {
            SecUtility.CheckParameter(ref rolename, true, true, true, 0x100, "roleName");
            SecUtility.CheckParameter(ref usernameToMatch, true, true, false, 0x100, "usernameToMatch");
            uint appid = ApplicationId;
            if (appid == 0)
                throw new ProviderException("Provider_role_not_found");
            uint roleid = AspNetRolesDTO.GetRoleId(rolename, appid);
            if (roleid == 0)
                throw new ProviderException("Provider_role_not_found");

            StringCollection collection1 = AspNetUsersDTO.UsersInRoles_FindUsersInRole(appid, roleid, usernameToMatch);
            if ((collection1 != null) && (collection1.Count > 0))
            {
                string[] textArray1 = new string[collection1.Count];
                collection1.CopyTo(textArray1, 0);
                return textArray1;
            }
            return new string[0];
        }

        private uint ApplicationId
        {
            get
            {
                return AspNetApplicationsDTO.GetApplicationId(_AppName);
            }
        }

    }
}